﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;

namespace CommSvcCreator
{
    class Program
    {
        [DllImport("kernel32.dll")]
        public static extern int AllocConsole();

        static void Main(string[] args)
        {
            if(args.Length == 0){
                WindowsIdentity current = WindowsIdentity.GetCurrent();
                Application.EnableVisualStyles();
                WindowsPrincipal windowsPrincipal = new WindowsPrincipal(current);
                string environmentVariable = Environment.GetEnvironmentVariable("WAITFOREXIT", EnvironmentVariableTarget.Process);
                string debugMode = Environment.GetEnvironmentVariable("DEBUGMODE");
                if (debugMode == "1" || debugMode == "true")
                {
                    AllocConsole();
                    Console.WriteLine("GetZipFileCount=>" + FileUtil.GetZipFileCount());
                    Console.Read();
                }
                if (windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator))
                {
                    if (FileUtil.GetZipFileCount() > 1){
                        MessageBox.Show("zip文件只能保留一个");
                        return;
                    }

                    if (!System.IO.File.Exists("c:\\windows\\system32\\nssm.exe"))
                    {
                        FileUtil.ExtractResFile("CommSvcCreator.resc.nssm.exe", "c:\\windows\\system32\\nssm.exe");
                    }

                    //一种是自解压安装zip压缩包中的可执行程序,一种是嵌入资源的释放安装
                    //有d盘就优先安装在d盘,没有d盘就优先安装在c盘

                    String unzipPath = "C:\\programfiles\\";
                    if (Directory.Exists("D:\\"))
                    {
                        unzipPath = "D:\\programfiles\\";
                    }

                    if (!Directory.Exists(unzipPath))
                    {
                        Directory.CreateDirectory(unzipPath);
                    }

                    if(debugMode == "1" || debugMode == "true")
                    {
                        Console.WriteLine("GetMainZipName=>" + FileUtil.GetMainZipName());
                        Console.Read();
                    }
                    string mainzipName = FileUtil.GetMainZipName();
                    string res_zip_file = unzipPath + mainzipName + ".zip";
                    
                    FileUtil.ExtractResFile("CommSvcCreator.resc."+ mainzipName + ".zip", res_zip_file);
                    if (debugMode == "1" || debugMode == "true")
                    {
                        Console.WriteLine("res_zip_file=>" + res_zip_file);
                        Console.Read();
                    }
                    Environment.SetEnvironmentVariable("zipfile", res_zip_file, EnvironmentVariableTarget.Process);

                    //由此留下了一个疑问 在两个进程之间如何去传递环境变量呢
                    string debug = Environment.GetEnvironmentVariable("debug");
                    string debug_zip_file = Environment.GetEnvironmentVariable("debug_zip_file");
                    debug = "0";
                    if (debug != null && (debug.ToLower() == "true" || debug == "1"))
                    {
                        if (debug_zip_file != null && debug_zip_file != "")
                        {
                            Environment.SetEnvironmentVariable("zipfile", debug_zip_file, EnvironmentVariableTarget.Process);
                        }

                    }
                    string zipfile = Environment.GetEnvironmentVariable("zipfile", EnvironmentVariableTarget.Process);
                    String zipfilename = new FileInfo(zipfile).Name;
                    String nameWoExt = zipfilename.Substring(0, zipfilename.LastIndexOf("."));
                    String svcname = nameWoExt;

                    String stopcmd = "net stop $svcname & sc delete $svcname";
                    stopcmd = stopcmd.Replace("$svcname", svcname);
                    ProcessStartInfo startInfo0 = new ProcessStartInfo("cmd", " /c " + stopcmd);
                    startInfo0.CreateNoWindow = true;
                    startInfo0.UseShellExecute = false;
                    startInfo0.RedirectStandardOutput = true;
                    Process process0 = Process.Start(startInfo0);
                    process0.WaitForExit();

                    if (File.Exists(zipfile))
                    {
                        using (var unzip = new Unzip(zipfile))
                        {
                            if (Directory.Exists(unzipPath + mainzipName))
                            {
                                try
                                {
                                    Directory.Delete(unzipPath + mainzipName, true);
                                }
                                catch (Exception exc)
                                {
                                    MessageBox.Show("删除失败:" + exc.ToString());
                                }
                            }

                            try
                            {
                                unzip.ExtractToDirectory(unzipPath);
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show("解压出错=>" + ex.ToString());
                            }
                        }

                    }

                    //这些命令可以组合成一个批处理文件 将这些命令集合起来 最后用一次执行所有命令
                    string installcmd = "nssm install $svcname $workdir\\run.bat & nssm set $svcname AppDirectory $workdir & nssm set $svcname AppStdout $workdir\\out.log & nssm set $svcname AppStderr $workdir\\err.log & net start $svcname";
                    installcmd = installcmd.Replace("$svcname", svcname)
                                            .Replace("$workdir", unzipPath + svcname);

                    ProcessStartInfo startInfo = new ProcessStartInfo("cmd", " /c " + installcmd);
                    startInfo.CreateNoWindow = true;
                    startInfo.UseShellExecute = false;
                    startInfo.RedirectStandardOutput = true;
                    Process process = Process.Start(startInfo);
                    process.WaitForExit();
                    MessageBox.Show("安装完成");
                }
                else
                {

                    ProcessStartInfo processStartInfo = new ProcessStartInfo();
                    processStartInfo.FileName = Application.ExecutablePath;
                    processStartInfo.Arguments = string.Join(" ", args);
                    processStartInfo.Verb = "runas";
                    Process process3 = Process.Start(processStartInfo);
                    if (environmentVariable == "1")
                    {
                        process3.WaitForExit();
                    }
                    Application.Exit();
                }
            }
            else{
                AllocConsole();
                Dictionary<String, String> dic = new Dictionary<string, string>();
                foreach(string arg in args){
                    string[] arr = arg.Split(new char[] { '=' });
                    if (arr.Length > 1)
                    {
                        if (!dic.ContainsKey(arr[0]))
                        {
                            dic.Add(arr[0], arr[1]);
                        }
                    }
                    else if(arr.Length > 0){
                        dic.Add(arr[0],"");
                    }
                }

                if (dic.ContainsKey("/?") || dic.ContainsKey("-help") || dic.ContainsKey("--help")) {
                    Console.WriteLine("setup.exe --help");
                    Console.WriteLine("setup.exe --printResources or setup.exe --p to Show All Embbed Resources");
                    Console.WriteLine("setup.exe --showmainzip or setup.exe -smz");
                    Console.WriteLine("setup.exe --insertzip=xxxx.zip or setup.exe --i=xxxx.zip");
                }
                else if (dic.ContainsKey("--printResources") || dic.ContainsKey("-p") || dic.ContainsKey("--p"))
                {
                    string[] res = FileUtil.EnumAllResources();
                    foreach (string r in res) {
                        Console.WriteLine("Embbed Resource=> " + r);
                    }
                } else if (dic.ContainsKey("--showmainzip") || dic.ContainsKey("-smz")) {
                    string mainZipName = FileUtil.GetMainZipName();
                    Console.WriteLine("mainzipname=>" + mainZipName);
                } else if (dic.ContainsKey("--insertzip") || dic.ContainsKey("-i")) {
                    string zipfile = "";
                    if (dic.ContainsKey("--insertzip"))
                    {
                        zipfile = dic["--insertzip"];
                    } else if (dic.ContainsKey("-i"))
                    {
                        zipfile = dic["-i"];
                    }
                    Console.WriteLine("insert zipfile to setup.exe as Embbed Resource");

                    string tempPath = FileUtil.extract2TempPath("source");
                    string workdir = tempPath;
                    string cmdline = " /out:setup_emb.exe /platform:x64 /target:winexe /res:$zipfile,CommSvcCreator.resc."+zipfile+ ",public /res:$workdir\\source\\nssm.exe,CommSvcCreator.resc.nssm.exe,public $workdir\\source\\FileUtil.cs $workdir\\source\\Program.cs $workdir\\source\\Unzip.cs";
                    cmdline = cmdline.Replace("$zipfile", zipfile).Replace("$workdir",workdir);
                    Console.WriteLine("编译命令=>" + cmdline);

                    ProcessStartInfo startInfo = new ProcessStartInfo("csc", " " + cmdline);
                    startInfo.UseShellExecute = false;

                    Process process = Process.Start(startInfo);
                    process.WaitForExit();
                }else if(dic.ContainsKey("--extractsource") || dic.ContainsKey("-xts")){
                    FileUtil.extract2TempPath("source");
                }
                Console.Read();
            }
        }
    }
}
